﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Network.Tcp;

public abstract class TcpClientBase : TcpBase, ITimer
{
    public TcpClientBase(string name)
        :base(name)
    {
    }
    public override bool Init()
    {
        return true;
    }
    public bool Connect(IPEndPoint? ipEndPoint)
    {
        if (ipEndPoint == null)
            return false;
        Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            socket.Connect(ipEndPoint);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Connect Failed. ipEndPoint:{ipEndPoint}, Message:{ex.ToString()}");
            socket.Close();
            return false;
        }
        ConnectData connectData = new ConnectData();
        connectData.SessionID = TcpUtility.GetSessionID();
        connectData.Socket = socket;
        connectData.IPEndPoint = ipEndPoint;
        AddConnect(connectData);
        return true;
    }
    public bool AddConnectTarget(IPEndPoint ipEndPoint)
    {
        var connectTarget = GetConnectTarget(ipEndPoint);
        if (connectTarget != null)
        {
            return false;
        }
        connectTarget = new ConnectTarget();
        connectTarget.IPEndPoint = ipEndPoint;
        lock (ConnectTargetMutex)
        {
            ConnectTargets.Add(connectTarget);
        }
        return true;
    }
    protected ConnectTarget? GetConnectTarget(IPEndPoint? ipEndPoint)
    {
        if (ipEndPoint == null)
            return null;
        lock (ConnectTargetMutex)
        {
            return ConnectTargets.FirstOrDefault(connectTarget => ipEndPoint.Equals(connectTarget.IPEndPoint));
        }
    }
    protected override void RemoveConnect(ConnectData connectData)
    {
        var connectTarget = GetConnectTarget(connectData.IPEndPoint);
        if (connectTarget != null)
        {
            connectTarget.IsConnected = false;
        }
        base.RemoveConnect(connectData);
    }
    protected void CheckClientConnect()
    {
        lock (ConnectTargetMutex)
        {
            foreach (var connectTarget in ConnectTargets)
            {
                if (!connectTarget.IsConnected)
                {
                    connectTarget.IsConnected = Connect(connectTarget.IPEndPoint);
                }
            }
        }
    }
    void ITimer.OnTimer()
    {
        CheckClientConnect();
    }
    public override void ThreadInit()
    {
        CheckClientConnect();
    }
    protected override void Run()
    {
        base.Run();
        (this as ITimer).CheckTimer();
    }
    public override void ThreadExit()
    {
        base.ThreadExit();
        ConnectTargets.Clear();
    }



    readonly object ConnectTargetMutex = new object();
    protected List<ConnectTarget> ConnectTargets = new List<ConnectTarget>();


    bool HasSetTimer = false;
    int TimeInterval;
    int EventCount = 0;
    int CurrentEventCount = 0;
    DateTime LastTimer;
    int ITimer.TimeOutMicroSecond { get => TimeOutMicroSecond; set => TimeOutMicroSecond = value; }
    bool ITimer.HasSetTimer { get => HasSetTimer; set => HasSetTimer = value; }
    int ITimer.TimeInterval { get => TimeInterval; set => TimeInterval = value; }
    int ITimer.EventCount { get => EventCount; set => EventCount = value; }
    int ITimer.CurrentEventCount { get => CurrentEventCount; set => CurrentEventCount = value; }
    DateTime ITimer.LastTimer { get => LastTimer; set => LastTimer = value; }
}
